﻿using Decisions.HL7.Message;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace Decisions.HL7.DataTypes
{
    public class DTM : AbstractDataType
    {

        public DateTime? Value { get; set; }

        private static Dictionary<int, string> LENGTH_TO_FORMATS = new Dictionary<int, string>();
        static DTM() {

            LENGTH_TO_FORMATS[8] = "yyyyMMdd";
            LENGTH_TO_FORMATS[12] = "yyyyMMddHHmm";
            LENGTH_TO_FORMATS[14] = "yyyyMMddHHmmss";
            LENGTH_TO_FORMATS[17] = "yyyyMMddHHmmssfff";
            LENGTH_TO_FORMATS[18] = "yyyyMMddHHmmssffff";
        }

            public override void Parse(string parseableText, HL7ParserOptions options, string dataName, char? whichSep)
            {

                if (string.IsNullOrWhiteSpace(parseableText)) Value = null;
                else
                {
                    string originalText = parseableText;
                    string timezone = null;
                    int tzIndex = parseableText.IndexOf('+');
                    if (tzIndex == -1) tzIndex = parseableText.IndexOf('-');
                    if (tzIndex >= 0)
                    {
                        timezone = parseableText.Substring(tzIndex + 1);
                        parseableText = parseableText.Substring(0, tzIndex);
                    }

                    // Parsing date/time

                    // If there's a dot, remove it.
                    parseableText = parseableText.Replace(".", string.Empty);
                    string format = null;
                    if (LENGTH_TO_FORMATS.ContainsKey(parseableText.Length))
                    {
                        format = LENGTH_TO_FORMATS[parseableText.Length];
                    }

                    if (string.IsNullOrEmpty(format)) {
                        throw new Exception(string.Format("Cannot determine the format for date: {0} original [{1}]", parseableText, originalText));
                    }

                    DateTime resultValue;
                    if (DateTime.TryParseExact(parseableText, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out resultValue))
                    {
                        Value = resultValue;
                    }
                    else
                    {
                        Value = null;
                        throw new Exception(dataName + " could not be parsed as a date");
                    }

                    if (timezone != null) {
                        // Need to deal with this.
                    }
                }
            }


            public override string GetER7(HL7ParserOptions options)
            {
                return Value != null ? Value.Value.ToString("yyyyMMddHHmmssfff") : null;
            }
    }
}
